package MONITORING::MW::TOMCAT::MEMORY;

#################################################################
# $LastChangedDate: 2013-11-25 15:03:06 +0000 (Mon, 25 Nov 2013) $
# $LastChangedRevision: 22 $
# $LastChangedBy: aswod_83@gmx.net $
#################################################################
use strict;
use base qw(moniCA::HTTP::REQUEST);
use XML::Simple;
use Data::Dumper;

#-------------------------------------------------------------------------------
sub Run {

#-------------------------------------------------------------------------------
# Description:
# Input Parms:
# Output Parms:
#-------------------------------------------------------------------------------
    my $self      = shift;
    my $cnf       = $self->GetCNF();
    my $logger    = $self->GetLogger();
    my $statefile = $self->TmpDir() . '/' . $self->Plug() . '.xml';
    my $ref;
    my $oldstat;
    my %newstat;

    if ( -s $statefile ) {
        $oldstat = XMLin( $statefile, ForceArray => 1 );
    }

    $self->ConnectHTTP(@_);
    if ( $self->{HTTPRequest}->is_success ) {

        my %memory;
        $memory{free_allocated_mem} = XMLin(
            $self->{HTTPRequest}->content,
            ForceArray => ['connector'],
            KeyAttr    => []
        )->{jvm}->{memory}->{free};
        $memory{free_global_mem} = (
            XMLin(
                $self->{HTTPRequest}->content,
                ForceArray => ['connector'],
                KeyAttr    => []
              )->{jvm}->{memory}->{max} - XMLin(
                $self->{HTTPRequest}->content,
                ForceArray => ['connector'],
                KeyAttr    => []
              )->{jvm}->{memory}->{total}
        );

        foreach my $mem ( keys %memory ) {

            if ( $cnf->{jvm}->{memory}->{$mem} ) {

                if (
                    $memory{$mem} < $cnf->{jvm}->{memory}->{$mem}->{failBytes} )
                {
                    $newstat{memory}{$mem}{failBytes} =
                      ( $oldstat->{memory}->{$mem}->{failBytes} + 1 ) || 1;
                    $newstat{memory}{$mem}{warnBytes} = 0;
                    if ( $newstat{memory}{$mem}{failBytes} == $cnf->{maxCount} )
                    {
                        $logger->error( $mem . ": "
                              . $memory{$mem}
                              . " ($newstat{memory}{$mem}{failBytes})" );
                    }
                    else {
                        $logger->warn( $mem . ": "
                              . $memory{$mem}
                              . " ($newstat{memory}{$mem}{failBytes})" );
                    }
                }
                elsif (
                    $memory{$mem} < $cnf->{jvm}->{memory}->{$mem}->{warnBytes} )
                {
                    $newstat{memory}{$mem}{warnBytes} =
                      ( $oldstat->{memory}->{$mem}->{warnBytes} + 1 ) || 1;
                    $newstat{memory}{$mem}{failBytes} = 0;
                    if ( $newstat{memory}{$mem}{warnBytes} == $cnf->{maxCount} )
                    {
                        $logger->warn( $mem . ": "
                              . $memory{$mem}
                              . " ($newstat{memory}{$mem}{warnBytes})" );
                    }
                    else {
                        $logger->info( $mem . ": "
                              . $memory{$mem}
                              . " ($newstat{memory}{$mem}{warnBytes})" );
                    }
                }
                else {
                    $newstat{memory}{$mem}{failBytes} = 0;
                    $newstat{memory}{$mem}{warnBytes} = 0;
                    $logger->info( $mem . ": " . $memory{$mem} );
                }
            }
            else {
                $logger->debug("missing config parameter $mem");
                next;
            }
        }
        $self->Report() if ( $cnf->{'Report'} =~ /true/i );
        $newstat{connection} = 0;
    }
    else {
        $newstat{connection} = ( $oldstat->{connection} + 1 ) || 1;
        $newstat{memory} = $oldstat->{memory};
        if ( $newstat{connection} == $cnf->{max_event_count} ) {
            $logger->error( "No Request (", $self->{HTTPRequest}->status_line,
                ")" );
        }
        else {
            $logger->warn( "No Request (", $self->{HTTPRequest}->status_line,
                ")" );
        }
    }
    XMLout( \%newstat, outputfile => $statefile, NoSort => 0 );
}

#-------------------------------------------------------------------------------
sub Report {

#-------------------------------------------------------------------------------
# Description:  Creating/Updating RRD File
# Input Parms:
# Output Parms: None
#-------------------------------------------------------------------------------

    my $self    = shift;
    my $logger  = $self->GetLogger();
    my $cnf     = $self->GetCNF();
    my $rrdfile = $self->VarDir() . '/' . $self->Plug() . '.rrd';

    eval {
        require RRDs;

        if ( !-f $self->VarDir() . '/' . $self->Plug() . '.rrd' ) {
            RRDs::create(
                $self->VarDir() . '/' . $self->Plug() . '.rrd',
                "--step=300",
                "DS:free:GAUGE:600:0:100000000000",
                "DS:total:GAUGE:600:0:100000000000",
                "DS:max:GAUGE:600:0:100000000000",
                "RRA:AVERAGE:0.5:1:800",
                "RRA:AVERAGE:0.5:6:800",
                "RRA:AVERAGE:0.5:24:800",
                "RRA:AVERAGE:0.5:288:800",
                "RRA:MAX:0.5:1:800",
                "RRA:MAX:0.5:6:800",
                "RRA:MAX:0.5:24:800",
                "RRA:MAX:0.5:288:800"
            );
            $logger->warn( "RRDs::create returns " . RRDs::error() )
              if ( RRDs::error() );
        }

        if ( -f $self->VarDir() . '/' . $self->Plug() . '.rrd' ) {
            RRDs::update(
                $self->VarDir() . '/' . $self->Plug() . '.rrd',
                '--template=free:total:max',
                'N' . ':'
                  . XMLin(
                    $self->{HTTPRequest}->content,
                    ForceArray => ['connector'],
                    KeyAttr    => []
                  )->{jvm}->{memory}->{free}
                  . ':'
                  . XMLin(
                    $self->{HTTPRequest}->content,
                    ForceArray => ['connector'],
                    KeyAttr    => []
                  )->{jvm}->{memory}->{total}
                  . ':'
                  . XMLin(
                    $self->{HTTPRequest}->content,
                    ForceArray => ['connector'],
                    KeyAttr    => []
                  )->{jvm}->{memory}->{max}
            );
            $logger->warn( "RRDs::update returns " . RRDs::error() )
              if ( RRDs::error() );
        }
        1;
    } or $logger->info( "Report incomplete: " . $@ );

}

1;

__END__
 
=pod
 
=head1 NAME
 
MEMORY.pm - monitors service availability 
 
=head1 SYNOPSIS
 
=head1 DESCRIPTION
 
=head1 PREREQUISITES
 
The follwing CPAN modules needs to be installed:
 
C<Log::Log4perl>
C<XML::Simple>
C<IO::Socket::INET>
C<Time::HiRes>
=head1 CONFIGURATION FILE
 
  By default
 
=head2 EXAMPLES
 
=head3 example of configuation file
 
Modul 	    MONITORING::SYS::SOCKET_PORT
Logger		%LOGGER%
LogLevel	%PRIORITY%


<service %IDENTIFIER%>
						PeerAddr = %DESTINATION_IP%
 						PeerPort = %DESTINATION_PORT%
 						Proto = %PROTOCOL%
 						Timeout	= %TIMEOUT_SEC%
 						LocalAddr = %LOCAL_BIND_IP%
</service>

max_error_count =       3
 
=cut
